package com.awesome.network.call;

import com.awesome.network.OkHttpHelper;
import com.awesome.network.callback.Callback;
import com.awesome.network.callback.FailureRunnable;
import com.awesome.network.callback.SuccessRunnable;
import com.awesome.network.exception.NetworkUnavailableException;
import com.awesome.network.util.NetworkStateHelper;

import java.io.IOException;
import java.lang.reflect.Type;

import okhttp3.Call;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Author: JFangZ
 * Email:janezhang1901@163.com
 * Date: 2021/4/28 9:35
 * Description:Call impl for common request.
 */
public class CallImpl<T> extends AbsCall<T> {
    private final Type mType;

    public CallImpl(Call call, Type type) {
        super(call);
        mType = type;
    }

    @Override
    public void enqueue(Callback<T> callback) {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                callback.onFailure(new NetworkUnavailableException());
                return;
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        mCall.enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mHandler.post(new FailureRunnable<>(callback, e));
                OkHttpHelper.SINGLETON.removeCall(CallImpl.this);
            }

            @Override
            public void onResponse(Call call, Response response) {
                OkHttpHelper.SINGLETON.removeCall(CallImpl.this);
                try {
                    if (mType == Response.class) {
                        mHandler.post(new SuccessRunnable<>(callback, (T) response));
                    } else {
                        String string = response.body().string();
                        T t = mGson.fromJson(string, mType);
                        mHandler.post(new SuccessRunnable<>(callback, t));
                    }
                } catch (Exception e) {
                    mHandler.post(new FailureRunnable<>(callback, e));
                    OkHttpHelper.SINGLETON.removeCall(CallImpl.this);
                }
            }
        });
    }

    @Override
    public T execute() throws Exception {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                throw new NetworkUnavailableException();
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        Response response = mCall.execute();
        OkHttpHelper.SINGLETON.removeCall(this);
        if (mType == Response.class) {
            return (T) response;
        } else {
            ResponseBody responseBody = response.body();
            return mGson.fromJson(responseBody.string(), mType);
        }
    }

    @Override
    public <O> TransformCallImpl<T, O> transform(ResponseTransformer<T, O> responseTransformer) {
        if (mType == Response.class) {
            throw new UnsupportedOperationException();
        }
        return new TransformCallImpl<>(mCall, mType, responseTransformer);
    }
}